﻿using Solidinfo.BLL;
using Solidinfo.DAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;

namespace Solidinfo.Web.Helpers
{
    public interface IDisplayNameHelper
    {
        MvcHtmlString DisplayName(string expresss);
    }

    public interface IDisplayNameHelper<TModel> : IDisplayNameHelper
    {
        MvcHtmlString DisplayNameFor<TValue>(Expression<Func<TModel, TValue>> expression);
        string DisplayNameStringFor<TValue>(Expression<Func<TModel, TValue>> expression);
        MvcHtmlString MultilingualPlateCodeFor<TValue>(Expression<Func<TModel, TValue>> expression);
        string MultilingualPlateCodeStringFor<TValue>(Expression<Func<TModel, TValue>> expression);
    }

    public class DisplayNameHelper<TModel> : IDisplayNameHelper<TModel>
    {
        private static readonly DisplayNameHelper<TModel> __instance = new DisplayNameHelper<TModel>();
        public static DisplayNameHelper<TModel> Instance
        {
            get
            {
                return __instance;
            }
        }
        internal DisplayNameHelper()
        {

        }

        public MvcHtmlString DisplayName(string expresss)
        {
            throw new NotImplementedException();
        }

        public MvcHtmlString DisplayNameFor<TValue>(Expression<Func<TModel, TValue>> expression)
        {

            return DisplayNameExtensions.GetDisplayNameMvcString<TModel, TValue>(expression);
        }
        public string DisplayNameStringFor<TValue>(Expression<Func<TModel, TValue>> expression)
        {
            return DisplayNameExtensions.GetDisplayNameString<TModel, TValue>(expression);
        }

        public MvcHtmlString MultilingualPlateCodeFor<TValue>(Expression<Func<TModel, TValue>> expression)
        {
            return MultilingualHelper.GetMultilingualPlateCodeMvcStringFor<TModel, TValue>(expression);
        }

        public string MultilingualPlateCodeStringFor<TValue>(Expression<Func<TModel, TValue>> expression)
        {
            return MultilingualHelper.GetMultilingualPlateCodeStringFor<TModel, TValue>(expression);
        }
    }
    public static class DisplayNameExtensions
    {
        public static IDisplayNameHelper<TModel> GetDisplayNameHelper<TModel>(this HtmlHelper html)
        {
            return DisplayNameHelper<TModel>.Instance;
        }
        public static MvcHtmlString DisplayNameFor<TModel,TValue>(this HtmlHelper html,Expression<Func<TModel,TValue>> expression)
        {
            return GetDisplayNameMvcString<TModel, TValue>(expression);
        }

        public static string DisplayNameStringFor<TModel, TValue>(this HtmlHelper html, Expression<Func<TModel, TValue>> expression)
        {
            return GetDisplayNameString<TModel, TValue>(expression);
        }

        public static string GetDisplayNameString<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
        {
            ViewDataDictionary<TModel> viewdata = new ViewDataDictionary<TModel>();
            return GetDisplayNameString(ModelMetadata.FromLambdaExpression(expression, viewdata),
                                     ExpressionHelper.GetExpressionText(expression));
        }
        public static MvcHtmlString GetDisplayNameMvcString<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
        {
            ViewDataDictionary<TModel> viewdata = new ViewDataDictionary<TModel>();
            return GetDisplayNameMvcString(ModelMetadata.FromLambdaExpression(expression, viewdata),
                                     ExpressionHelper.GetExpressionText(expression));
        }
        internal static MvcHtmlString GetDisplayNameMvcString(ModelMetadata metadata, string htmlFieldName)
        {
            string s = metadata.DisplayName ?? (metadata.PropertyName ?? htmlFieldName.Split(new char[] { '.' }).Last<string>());
            return new MvcHtmlString(HttpUtility.HtmlEncode(s));
        }
        internal static string GetDisplayNameString(ModelMetadata metadata, string htmlFieldName)
        {
            string resolvedDisplayName = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();

            return resolvedDisplayName;
        }
        public static MvcHtmlString DisplayNameFor<TModel, TValue>(this HtmlHelper<IQueryable<TModel>> html, Expression<Func<TModel, TValue>> expression)
        {
            return GetDisplayNameMvcString(ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, new ViewDataDictionary<TModel>()), ExpressionHelper.GetExpressionText(expression));
        }
        

        public static MvcHtmlString DisplayNameFor<TModel, TValue>(this HtmlHelper<IPager<TModel>> html, Expression<Func<TModel, TValue>> expression)
            where TModel : class
        {
            return GetDisplayNameMvcString(ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, new ViewDataDictionary<TModel>()), ExpressionHelper.GetExpressionText(expression));
        }

        public static MvcHtmlString DisplayNameFor<TModel, TFilter, TValue>(this HtmlHelper<IPager<TModel, TFilter>> html, Expression<Func<TModel, TValue>> expression)
            where TFilter : new()
            where TModel : class
        {
            return GetDisplayNameMvcString(ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, new ViewDataDictionary<TModel>()), ExpressionHelper.GetExpressionText(expression));
        }

        public static MvcHtmlString DisplayNameForFilter<TModel, TFilter, TValue>(this HtmlHelper<IPager<TModel, TFilter>> html, Expression<Func<TFilter, TValue>> expression)
            where TFilter : new()
            where TModel : class
        {
            return DisplayNameExtensions.GetDisplayNameMvcString<TFilter, TValue>(expression);
        }
    }
}